// lock_guard example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex, std::lock_guard
#include <stdexcept>      // std::logic_error

std::mutex mtx;

void print_even ( int x )
{
    if ( x % 2 == 0 ) std::cout << x << " is even\n";
    else throw (std::logic_error("not even"));
}

void print_thread_id ( int id )
{
    try
    {
        // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:
        std::lock_guard<std::mutex> lck (mtx);
        print_even(id);
    }
    catch ( std::logic_error& )
    {
        std::cout << "[exception caught]\n";
    }
}

int main ()
{
    std::thread threads[10];
    // spawn 10 threads:
    for ( int i = 0; i < 10; ++ i )
    {
        threads[i] = std::thread(print_thread_id,i+1);
    }
    
    for (auto& th : threads) th.join();
    
    return 0;
}